package it.valeandre.omino.db;

import it.valeandre.omino.model.Match;
import it.valeandre.omino.model.Matches;
import it.valeandre.omino.model.Result;
import it.valeandre.omino.model.Results;
import it.valeandre.omino.utils.ResBundle;
import it.valeandre.omino.utils.Utils;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;

public class DbAdapter {

	private static final String TABLE_RESULTS = "results";

	private static final String KEY_ID = "id";
	private static final String KEY_HOME_TEAM = "home_team";
	private static final String KEY_AWAY_TEAM = "away_team";
	private static final String KEY_HOME_SCORE = "home_score";
	private static final String KEY_AWAY_SCORE = "away_score";
	private static final String KEY_HOME_DETAILS = "home_details";
	private static final String KEY_AWAY_DETAILS = "away_details";

	private DatabaseHelper mDBHelper;
	private SQLiteDatabase mDb;
	private static DbAdapter mInstance = null;

	private DbAdapter(Context context) {
		String dbName = ResBundle.DB_NAME;
		mDBHelper = new DatabaseHelper(context, dbName);

	}

	public static DbAdapter getInstance(Context context) {
		if (mInstance == null) {
			mInstance = new DbAdapter(context);
		}
		return mInstance;
	}

	public DbAdapter openDb() throws SQLException {
		mDb = mDBHelper.getWritableDatabase();
		return this;
	}

	public void closeDb() {
		mDBHelper.close();

	}

	private Results getResultsFromCursor(Cursor c) {
		Results results = new Results();

		if (c.moveToFirst()) {
			ArrayList<Result> resArray = new ArrayList<Result>();
			do {
				Result result = new Result();
				result.setHomeTeam(c.getString(1));
				result.setAwayTeam(c.getString(2));
				result.setHomeScore(c.getString(3));
				result.setAwayScore(c.getString(4));
				resArray.add(result);
			} while (c.moveToNext());
			results.setResults(resArray);
		} 

		return results;

	}
	
	private Matches getMatchesFromCursor(Cursor c) {
		Matches results = new Matches();

		if (c.moveToFirst()) {
			ArrayList<Match> resArray = new ArrayList<Match>();
			do {
				Match result = new Match();
				result.setHometeam(c.getString(1));
				result.setAwayteam(c.getString(2));
				result.setHomeGoals(c.getString(3));
				result.setAwayGoals(c.getString(4));
				result.setHomeGoalDetails(c.getString(5));
				result.setAwayGoalDetails(c.getString(6));
				resArray.add(result);
			} while (c.moveToNext());
			results.setList(resArray);
		} 

		return results;

	}
	
	public Results selectAllResults() {

		openDb();
		String query = "select * from " + TABLE_RESULTS;

		Cursor c = mDb.rawQuery(query, null);
		Results results = getResultsFromCursor(c);
		c.close();
		closeDb();
		return results;

	}
	
	private boolean deleteResults() {
			openDb();
			int ret = mDb.delete(TABLE_RESULTS, "1", null);
			closeDb(); 
			return ret > 0;
	}
	
	public boolean updateResults(Results results) {
		boolean ret = true;
		deleteResults();
		openDb();
		for(Result result: results.getResults()) {
			ContentValues values = new ContentValues();
			values.put(KEY_HOME_TEAM, result.getHomeTeam());
			values.put(KEY_AWAY_TEAM, result.getAwayTeam());
			values.put(KEY_HOME_SCORE, result.getHomeScore());
			values.put(KEY_AWAY_SCORE, result.getAwayScore());
			values.put(KEY_AWAY_SCORE, result.getAwayScore());
			long rowId = mDb.insert(TABLE_RESULTS, null, values);
			if(rowId == -1) {
				ret = false;
				break;
			}
		}

		closeDb();

		return ret;
	}
	
	public Matches selectAllMatches() {

		openDb();
		String query = "select * from " + TABLE_RESULTS;

		Cursor c = mDb.rawQuery(query, null);
		Matches results = getMatchesFromCursor(c);
		c.close();
		closeDb();
		return results;

	}
	
	public boolean updateMatches(Matches matches) {
		boolean ret = true;
		deleteResults();
		openDb();
		for(Match result: matches.getMatchList()) {
			ContentValues values = new ContentValues();
			values.put(KEY_HOME_TEAM, result.getHometeam());
			values.put(KEY_AWAY_TEAM, result.getAwayteam());
			values.put(KEY_HOME_SCORE, result.getHomeGoals());
			values.put(KEY_AWAY_SCORE, result.getAwayGoals());
			values.put(KEY_HOME_DETAILS, result.getHomeGoalDetails());
			values.put(KEY_AWAY_DETAILS, result.getAwayGoalDetails());
			long rowId = mDb.insert(TABLE_RESULTS, null, values);
			if(rowId == -1) {
				ret = false;
				break;
			}
		}

		closeDb();

		return ret;
	}

	private static class DatabaseHelper extends SQLiteOpenHelper {

		private Context mContext;
		private String mDbName;

		public DatabaseHelper(Context context, String databaseName) {
			super(context, databaseName, null, ResBundle.DB_VERSION);
			mContext = context;
			mDbName = databaseName;
			try {
				createDataBase();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		public void createDataBase() throws IOException {
			SQLiteDatabase db_Read = null;
			if (checkDataBase()) {
				Utils.log("w", "Database already exists");
			} else {
				Utils.log("w", "Database doesn't exists");
				db_Read = this.getReadableDatabase();
				db_Read.close();
				try {
					Utils.log("i", "Copying database");
					copyDataBase();
				} catch (IOException e) {
					e.printStackTrace();
					throw new Error(
							"OMINO | Error copying database");
				}
			}

		}

		private boolean checkDataBase() {

			SQLiteDatabase checkDB;
			boolean ret = false;

			try {
				String myPath = ResBundle.RES_DATABASE_PATH + mDbName;
				Utils.log("i", "Check DB: " + myPath);
				checkDB = SQLiteDatabase.openDatabase(myPath, null,
						SQLiteDatabase.NO_LOCALIZED_COLLATORS);
			} catch (SQLiteException e) {
				checkDB = null;
			}

			if (checkDB != null) {
				ret = true;
				checkDB.close();
			}

			return ret;
		}

		private void copyDataBase() throws IOException {

			Utils.log("i", "copy db from: " + "db/" + mDbName + ".sqlite");
			InputStream myInput = mContext.getAssets().open(
					"db/" + mDbName + ".sqlite");
			String outFileName = ResBundle.RES_DATABASE_PATH + mDbName;
			Utils.log("i", "copy db to: " + outFileName);
			OutputStream myOutput = new FileOutputStream(outFileName);
			byte[] buffer = new byte[1024];
			int length;
			while ((length = myInput.read(buffer)) > 0) {
				myOutput.write(buffer, 0, length);
			}
			myOutput.flush();
			myOutput.close();
			myInput.close();

		}

		public DatabaseHelper(Context context, String name,
				CursorFactory factory, int version) {
			super(context, name, factory, version);
		}

		@Override
		public void onCreate(SQLiteDatabase db) {

		}

		@Override
		public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

		}

	}

}
